package com.cyzy.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cyzy.dto.ResponseDto;
import com.cyzy.mapper.DriverMapper;
import com.cyzy.mapper.TripOrderMapper;
import com.cyzy.pojo.Driver;
import com.cyzy.pojo.TripOrder;
import com.cyzy.service.DriverService;
import com.cyzy.util.VerificationCodeUtil;
import com.cyzy.utils.DistanceCalculatorUtil;
import com.cyzy.utils.HashUtil;
import com.cyzy.utils.JwtUtil;
import com.cyzy.utils.RedisUtil;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class DriverServiceImpl extends ServiceImpl<DriverMapper, Driver> implements DriverService {

    @Autowired
    private DriverMapper driverMapper;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private TripOrderMapper tripOrderMapper;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;


    @Override
    public Map<String,Object> login(String acc, String password) {
        //根据账号或手机号查找用户并且用户的状态为0 （0：正常  1：禁用  2：删除）
        LambdaQueryWrapper<Driver> wrapper=new LambdaQueryWrapper<>();
        wrapper.and(queryWrapper -> queryWrapper
                        .eq(Driver::getDriverAcc,acc)
                        .or()
                        .eq(Driver::getPhone,acc)
                )
                .eq(Driver::getDriverStatus,0);
        Driver driver = driverMapper.selectOne(wrapper);
        if(driver == null){
            return null;
        }
        //校验密码
        if(!HashUtil.checkPassword(password,driver.getPassword())){
            return null;
        }
        //生成token
        Map<String,Object> map=new HashMap<>();
        map.put("id",driver.getDriverId());
        map.put("acc",driver.getDriverAcc());
        String token = JwtUtil.genToken(map);
        //存储token到redis
        redisUtil.set(token,token);
        redisUtil.setExpire(token,3600);
        //返回结果集给controller
        Map<String,Object> result=new HashMap<>();
        result.put("driver",driver);
        result.put("token",token);
        return result;
    }

    @Override
    public ResponseDto register(Driver driver) {
        //根据账号或手机号查找用户
        LambdaQueryWrapper<Driver> wrapper=new LambdaQueryWrapper<Driver>()
                .eq(Driver::getDriverAcc,driver.getDriverAcc())
                .or()
                .eq(Driver::getPhone,driver.getPhone());
        Driver user = this.getOne(wrapper);
        if(user!=null){
            return ResponseDto.fail("该用户已存在！");
        }
        String password = driver.getPassword();
        String encode = HashUtil.hashPassword(password);
        //密码加密
        driver.setPassword(encode);
        //添加用户
        int i = driverMapper.insert(driver);
        if(i<=0){
            return ResponseDto.fail("注册失败！");
        }
        return ResponseDto.ok("注册成功！");
    }



    @Override
    public int selectDriverType(int driverId) {
        return driverMapper.selectDriverType(driverId);
    }

    @Override
    public void forgotPassword(long driverId, String password) {

        //密码加密
        String newPassword = HashUtil.hashPassword(password);

        //重置密码
        UpdateWrapper<Driver> wrapper=new UpdateWrapper<>();
        wrapper.eq("driver_id",driverId)
                .set("password",newPassword);

        driverMapper.update(wrapper);
    }

    @Override
    public String getPhoneCode(String phone) throws Exception {
        // 1. 验证手机号格式
        if (!isValidPhoneNumber(phone)) {
            return "无效的手机号格式!";
        }

        // 2. 检查发送频率
        if (isRateLimited(phone)) {
            return "发送太频繁，请稍后再试！";
        }

        //2.1 检查手机号是否在司机表中存在
        LambdaQueryWrapper<Driver> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Driver::getPhone,phone);
        Driver driver = driverMapper.selectOne(wrapper);
        if( driver == null){
            return  "用户不存在！";
        }

        // 3. 生成验证码
        String code = VerificationCodeUtil.generateCode();


        //存入map中
        Map<String,Object> bodyMap = new HashMap<>();
        bodyMap.put("phone",phone);
        bodyMap.put("code",code);

        System.out.println(rocketMQTemplate + "   ----");
        System.out.println(rocketMQTemplate.getProducer());
        System.out.println(rocketMQTemplate.getConsumer());

        // 发送消息（异步方式）
        rocketMQTemplate.convertAndSend("rocket-send1", bodyMap);

        return "验证码已发送";
    }



    /*
    * redis存放订单状态orderStar：0是待接单,1是已接单，2是未接单
    *  */
    @Override
    public String automaticOrder(Long orderId) {
        System.out.println("==================================================");
        Driver nearest = null;
        double shortestDistance = Double.MAX_VALUE;

        System.out.println(redisTemplate.hasKey("orderStar"+orderId)  + "    ------irttr");
        //判断是否存在司机接单状态 0：未接单 1：已接单
        if(!redisTemplate.hasKey("orderStar"+orderId)){
            redisUtil.set("orderStar"+orderId,"0");
        }

        // 查询订单信息
        LambdaQueryWrapper<TripOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TripOrder::getOrderId, orderId);
        TripOrder tripOrder = tripOrderMapper.selectOne(wrapper);

        if (tripOrder.getOrderStatus() != 0) {
            return "该订单不属于待接单状态！";
        }
        System.out.println(redisUtil.get("orderStar"+orderId) + " --------订单orderStar");
        //如果司机接单
        if(redisUtil.get("orderStar"+orderId).equals("1")){
            System.out.println("oooooooooooooooooooooooopopopopopop");
            // 删除 Redis 中缓存的订单信息
            if(redisTemplate.hasKey(orderId.toString())){
                redisUtil.del(orderId.toString());
            }
            //删除redis中存储的订单状态
            if(redisTemplate.hasKey("orderStar"+orderId)){
                redisUtil.del("orderStar"+orderId);
            }
            //删除redis中存储的被拒单司机信息
            if(redisTemplate.hasKey("driverList" + orderId)){
                redisUtil.del("driverList" + orderId);
            }

            return "该订单已被司机接单！";
        }

        // 获取 Redis 中拒绝接单的司机列表
        String driverLis = "driverList" + orderId;

        // 解析车型和价格
        List<Integer> typeList = JSON.parseArray(tripOrder.getCarTypes(), Integer.class);
        Map<String, String> map = JSON.parseObject(tripOrder.getCarPrices(), new TypeReference<>() {});

        System.out.println(typeList + "————————————————typeList");
        System.out.println(map + "————————————————map");
        // 查询符合条件的司机
        List<Driver> drivers = driverMapper.selectDriverList(typeList);
        System.out.println("999999999999999999");
        System.out.println(drivers);
        System.out.println("999999999999999999");
        if (drivers == null || drivers.isEmpty()) {
            return "当前暂无空闲司机!";
        }

        List<String> rejectedDriverIds = redisTemplate.hasKey(driverLis)
                ? redisTemplate.opsForList().range(driverLis, 0, -1)
                : Collections.emptyList();

        System.out.println("999999999999999999");
        System.out.println(rejectedDriverIds + " -----rejectedDriverIds");
        System.out.println("999999999999999999");

        // 过滤掉已被拒单的司机
        List<Driver> availableDrivers = drivers.stream()
                .filter(driver -> !rejectedDriverIds.contains(String.valueOf(driver.getDriverId())))
                .toList();

        System.out.println("999999999999999999");
        System.out.println(availableDrivers +"    -----availableDrivers");
        System.out.println("999999999999999999");


        if (availableDrivers.isEmpty()) {
            return "当前暂无空闲司机或所有司机均已拒单!";
        }

        // 找最近的司机
        for (Driver driver : availableDrivers) {
            double distance = DistanceCalculatorUtil.calculateDistance(driver, tripOrder);
            if (distance < shortestDistance) {
                shortestDistance = distance;
                nearest = driver;
            }
        }
        System.out.println("============================nearest=====================");
        System.out.println(nearest+"============================nearest=============");
        System.out.println("============================nearest=====================");
        // 设置订单司机并更新数据库
        tripOrder.setDriverId(nearest.getDriverId());
        tripOrder.setPrice(Double.parseDouble(map.get(nearest.getCarModelId())));

        LambdaUpdateWrapper<TripOrder> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(TripOrder::getOrderId, orderId)
                .set(TripOrder::getDriverId, nearest.getDriverId())
                .set(TripOrder::getPrice, tripOrder.getPrice());

        tripOrderMapper.update(null, updateWrapper);
        LambdaQueryWrapper<TripOrder> wrappers = new LambdaQueryWrapper<>();
        wrappers.eq(TripOrder::getOrderId, orderId);
        TripOrder tripOrders = tripOrderMapper.selectOne(wrappers);
        //把司机订单存到reids中
        // 找到司机id
        String driverId = String.valueOf(tripOrders.getDriverId());

        // 构造 Redis Key，例如：orders:driver_123
        String key = "driversOrder:" + driverId;

        // 将订单转为 JSON 存入 Redis（可设置过期时间）
        String orderJson = JSON.toJSONString(tripOrders);
        redisTemplate.opsForValue().set(key, orderJson, 5, TimeUnit.MINUTES); // 过期时间5分钟

        return "等待司机确认订单";
    }

    @Override
    public void Offline(Driver driver) {
        //司机状态改成下线
        LambdaUpdateWrapper<Driver> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(Driver::getDriverId,driver.getDriverId())
                .set(Driver::getTakingStatus,driver.getTakingStatus())
                .set(Driver::getDriverX,0)
                .set(Driver::getDriverY,0);
        driverMapper.update(null,wrapper);
    }

    @Override
    public void upline(Driver driver) {
        //将司机状态改成上线，和传入位置信息
        LambdaUpdateWrapper<Driver> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(Driver::getDriverId,driver.getDriverId())
                .set(Driver::getTakingStatus,driver.getTakingStatus())
                .set(Driver::getDriverX,driver.getDriverX())
                .set(Driver::getDriverY,driver.getDriverY());
        driverMapper.update(null,wrapper);
    }
    //查询司机信息
    @Override
    public Driver getDriverByOrderId(String orderId) {
        return driverMapper.getDriverByOrderId(orderId);
    }


    //校验手机格式
    private boolean isValidPhoneNumber(String phone) {
        return phone != null && phone.matches("^1[3-9]\\d{9}$");
    }
    private boolean isRateLimited(String phone) {
        String key = "SMS_RATE_LIMIT:" + phone;
        String count = redisUtil.get(key);
        if (count == null) {
            redisUtil.set(key, "1");
            redisUtil.setExpire(key, 60); // 1分钟内限制
            return false;
        }
        int currentCount = Integer.parseInt(count);
        if (currentCount >= 3) { // 1分钟内最多发送3次
            return true;
        }
        redisUtil.set(key, String.valueOf(currentCount + 1));
        return false;
    }
}
